/**
 * Copyright 2011-2011 - Members of the Chaupal Community
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */


package net.chaupal.Impl.Tools;
import java.math.BigInteger;
import java.util.Locale;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class provides a mean to activate debugging code at implementation time
 * and to disactivate it at runtime (for example). It can be used to check
 * assertions.
 * <p>
 * The debugging code is activated if and only if {@link #SOUNDNESS_ENABLED}
 * is <tt>true</tt>.
 */
public final class Soundness {

    /**
     *  Logger
     */
    private final static Logger LOG = LoggerFactory.getLogger(Soundness.class);

    /**
     * Indicates whether soundness checks are enabled. By default, the boolean
     * is set to true.
     * It can be configured with the {@code net.generics.soundness.enable}
     * property.
     */
    public static final boolean SOUNDNESS_ENABLED
            = Boolean.parseBoolean(
            System.getProperty(
            "net.generics.soundness.enable", Boolean.TRUE.toString()));

    public static String mergeMessages(String first, String... messages) {
        
        // Sanity
        if ( ( first == null ) && ( messages == null ) ) return null;
        
        // Preparing result
        StringBuilder result = new StringBuilder();
        
        for (int i=0;i<messages.length;i++) {
            result.append(messages[i]).append("\n");
        }
        
        // Returning result
        return result.toString();
        
    }
    
    /**
     * Throws a {@link NullPointerException} and logs an error entry
     * if the parameter is <tt>null</tt>;
     *
     * @param inLOG A {@code Logger}
     * @param TheParameter The object to check
     * @param messages messages to add to the log 
     */
    public static void nullParameter(Logger inLOG, Object TheParameter,
            String... messages) {

        if ( !SOUNDNESS_ENABLED ) return;

        if (TheParameter==null) {

            final String Tmp
                    = mergeMessages("Null parameter encountered", messages);
            final NullPointerException Ex = new NullPointerException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the parameter is lesser than {@code Min}
     * or greater than {@code Max}, or if {@code Min} greater than {@code Max}.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code double} to check
     * @param Min a {@code double}
     * @param Max a {@code double}
     * @param messages messages to add to the log 
     */
    public static void rangeIncludedDouble(
            Logger inLOG, double TheParameter, double Min, double Max,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameters
        if ( Min > Max ) {

            final String Tmp
                    = mergeMessages( "Min=" + Min + " > Max=" + Max, messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

        if ( ( TheParameter > Max ) || ( TheParameter < Min ) ) {

            final String Tmp
                    = mergeMessages("Parameter=" + TheParameter
                    + " not in range [" + Min + "," + Max + "]", messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the parameter is lesser than {@code Min}
     * or greater than {@code Max}, or if {@code Min} greater than {@code Max}.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code float} to check
     * @param Min a {@code float}
     * @param Max a {@code float}
     * @param messages messages to add to the log 
     */
    public static void rangeIncludedFloat(
            Logger inLOG, float TheParameter, float Min, float Max,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameters
        if ( Min > Max ) {

            final String Tmp
                    = mergeMessages("Min=" + Min + " > Max=" + Max, messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

        if ( ( TheParameter > Max ) || ( TheParameter < Min ) ) {

            final String Tmp
                    = mergeMessages("Parameter=" + TheParameter
                    + " not in range [" + Min + "," + Max + "]", messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the parameter is lesser than {@code Min}
     * or greater than {@code Max}, or if {@code Min} greater than {@code Max}.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code long} to check
     * @param Min a {@code long}
     * @param Max a {@code long}
     * @param messages messages to add to the log 
     */
    public static void rangeIncludedLong(
            Logger inLOG, long TheParameter, long Min, long Max,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameters
        if ( Min > Max ) {

            final String Tmp
                    = mergeMessages("Min=" + Min + " > Max=" + Max, messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

        if ( ( TheParameter > Max ) || ( TheParameter < Min ) ) {

            final String Tmp
                    = mergeMessages("Parameter=" + TheParameter
                    + " not in range [" + Min + "," + Max + "]", messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the parameter is lesser than {@code Min}
     * or greater than {@code Max}, or if {@code Min} greater than {@code Max}.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code int} to check
     * @param Min an {@code int}
     * @param Max an {@code int}
     * @param messages messages to add to the log 
     */
    public static void rangeIncludedInteger(
            Logger inLOG, int TheParameter, int Min, int Max,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameters
        if ( Min > Max ) {

            final String Tmp
                    = mergeMessages("Min=" + Min + " > Max=" + Max, messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

        if ( ( TheParameter > Max ) || ( TheParameter < Min ) ) {

            final String Tmp
                    = mergeMessages("Parameter=" + TheParameter +
                    " not in range [" + Min + "," + Max + "]", messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the parameter is lesser than {@code Min}
     * or greater than {@code Max}, or if {@code Min} greater than {@code Max}.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code BigInteger} to check
     * @param Min an {@code BigInteger}
     * @param Max an {@code BigInteger}
     * @param messages messages to add to the log 
     */
    public static void rangeIncludedBigInteger(
            Logger inLOG, BigInteger TheParameter,
            BigInteger Min, BigInteger Max,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameters
        Soundness.nullParameter(LOG, TheParameter);
        Soundness.nullParameter(LOG, Min);
        Soundness.nullParameter(LOG, Max);

        if ( Min.compareTo(Max) > 0 ) {

            final String Tmp
                    = mergeMessages("Min=" + Min.toString()
                    + " > Max=" + Max.toString(), messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

        if ( ( TheParameter.compareTo(Max) > 0 )
                || ( TheParameter.compareTo(Min) < 0 ) ) {

            final String Tmp
                    = mergeMessages("Parameter=" + TheParameter.toString()
                    + " not in range [" + Min.toString()
                    + "," + Max.toString() + "]", messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the parameter does not match the expected value.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code boolean} to check
     * @param ExpectedValue The expected {@code boolean} value
     * @param messages messages to add to the log 
     */
    public static void expectedValueBoolean(
            Logger inLOG, Boolean TheParameter, Boolean ExpectedValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameters
        Soundness.nullParameter(LOG, TheParameter);
        Soundness.nullParameter(LOG, ExpectedValue);

        if (TheParameter.booleanValue() != ExpectedValue.booleanValue()) {

            final String Tmp
                    = mergeMessages("Parameter='" + TheParameter
                    + "' does not have expected value='" + ExpectedValue + "'",
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry if
     * the parameter does not match the expected value.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code String} to check
     * @param ExpectedValue The expected {@code String} value
     * @param messages messages to add to the log 
     */
    public static void expectedValueString(
            Logger inLOG, String TheParameter, String ExpectedValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameters
        Soundness.nullParameter(LOG, TheParameter);
        Soundness.nullParameter(LOG, ExpectedValue);

        if (TheParameter.compareTo(ExpectedValue)!=0) {

            final String Tmp
                    = mergeMessages("Parameter='" + TheParameter
                    + "' does not have expected value='" + ExpectedValue + "'",
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry if the
     * parameter does not match the expected value.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code String} to check
     * @param ExpectedValue The expected {@code String} value
     * @param messages messages to add to the log 
     */
    public static void expectedValueChar(
            Logger inLOG, char TheParameter, char ExpectedValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( TheParameter != ExpectedValue ) {

            final String Tmp
                    = mergeMessages("Parameter='" + TheParameter
                    + "' does not have expected value='" + ExpectedValue + "'",
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the parameter does not match the expected value.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code double} to check
     * @param ExpectedValue The expected {@code double} value
     * @param messages messages to add to the log 
     */
    public static void expectedValueDouble(
            Logger inLOG, double TheParameter, double ExpectedValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameter
        if (TheParameter!=ExpectedValue) {

            final String Tmp
                    = mergeMessages("Parameter='" + TheParameter
                    + "' does not have expected value='" + ExpectedValue + "'",
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the parameter does not match the expected value.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code float} to check
     * @param ExpectedValue The expected {@code float} value
     * @param messages messages to add to the log 
     */
    public static void expectedValueFloat(
            Logger inLOG, float TheParameter, float ExpectedValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameter
        if (TheParameter!=ExpectedValue) {

            final String Tmp
                    = mergeMessages("Parameter='" + TheParameter
                    + "' does not have expected value='" + ExpectedValue + "'",
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the parameter does not match the expected value.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code long} to check
     * @param ExpectedValue The expected {@code long} value
     * @param messages messages to add to the log 
     */
    public static void expectedValueLong(
            Logger inLOG, long TheParameter, long ExpectedValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameter
        if ( TheParameter != ExpectedValue ) {

            final String Tmp
                    = mergeMessages("Parameter='" + TheParameter 
                    + "' does not have expected value='" + ExpectedValue + "'",
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the parameter does not match the expected value.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code BigInteger} to check
     * @param ExpectedValue The expected {@code BigInteger} value
     * @param messages messages to add to the log 
     */
    public static void expectedValueBigInteger(
            Logger inLOG, BigInteger TheParameter, BigInteger ExpectedValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameter
        Soundness.nullParameter(LOG, TheParameter);
        Soundness.nullParameter(LOG, ExpectedValue);

        if ( TheParameter.compareTo(ExpectedValue)!=0 ) {

            final String Tmp
                    = mergeMessages("Parameter='" + TheParameter.toString()
                    + "' does not have expected value='"
                    + ExpectedValue.toString() + "'",
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the parameter does not match the expected value.
     *
     * @param inLOG a {@code Logger}
     * @param TheParameter The {@code int} to check
     * @param ExpectedValue The expected {@code int} value
     * @param messages messages to add to the log 
     */
    public static void expectedValueInteger(
            Logger inLOG, int TheParameter, int ExpectedValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking value
        if ( TheParameter != ExpectedValue ) {

            final String Tmp
                    = mergeMessages("Parameter='" + TheParameter
                    + "' does not have expected value='" + ExpectedValue + "'",
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code Higher} is lesser or equal to {@code Lower}.
     *
     * @param inLOG a {@code Logger}
     * @param Higher The higher {@code int} to check
     * @param Lower The lower {@code int} to check
     * @param messages messages to add to the log 
     */
    public static void greaterThanInteger(Logger inLOG, int Higher, int Lower,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking values
        if ( Higher <= Lower ) {

            final String Tmp
                    = mergeMessages("Higher=" + Higher
                    + " not greater than Lower=" + Lower,
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code Higher} is lesser or equal to {@code Lower}.
     *
     * @param inLOG a {@code Logger}
     * @param Higher The higher {@code long} to check
     * @param Lower The lower {@code long} to check
     * @param messages messages to add to the log 
     */
    public static void greaterThanLong(Logger inLOG, long Higher, long Lower,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking values
        if ( Higher <= Lower ) {

            final String Tmp
                    = mergeMessages("Higher=" + Higher
                    + " not greater than Lower=" + Lower,
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code Higher} is lesser or equal to {@code Lower}.
     *
     * @param inLOG a {@code Logger}
     * @param Higher The higher {@code float} to check
     * @param Lower The lower {@code float} to check
     * @param messages messages to add to the log 
     */
    public static void greaterThanFloat(
            Logger inLOG, float Higher, float Lower,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking values
        if ( Higher <= Lower ) {

            final String Tmp
                    = mergeMessages("Higher=" + Higher
                    + " not greater than Lower=" + Lower,
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code Higher} is lesser or equal to {@code Lower}.
     *
     * @param inLOG a {@code Logger}
     * @param Higher The higher {@code double} to check
     * @param Lower The lower {@code double} to check
     * @param messages messages to add to the log 
     */
    public static void greaterThanDouble(
            Logger inLOG, double Higher, double Lower,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking values
        if ( Higher <= Lower ) {

            final String Tmp
                    = mergeMessages("Higher=" + Higher
                    + " not greater than Lower=" + Lower,
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code Higher} is lesser or equal to {@code Lower}.
     *
     * @param inLOG a {@code Logger}
     * @param Higher The higher {@code BigInteger} to check
     * @param Lower The lower {@code BigInteger} to check
     * @param messages messages to add to the log 
     */
    public static void greaterThanBigInteger(
            Logger inLOG, BigInteger Higher, BigInteger Lower,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameter
        Soundness.nullParameter(LOG, Higher);
        Soundness.nullParameter(LOG, Lower);

        // Checking values
        if ( Higher.compareTo(Lower) <= 0 ) {

            final String Tmp
                    = mergeMessages("Higher=" + Higher.toString()
                    + " not greater than Lower=" + Lower.toString(),
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code Higher} is lesser than {@code Lower}.
     *
     * @param inLOG a {@code Logger}
     * @param Higher The higher {@code double} to check
     * @param Lower The lower {@code double} to check
     * @param messages messages to add to the log 
     */
    public static void greaterOrEqualToDouble(
            Logger inLOG, double Higher, double Lower,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking values
        if ( Higher < Lower ) {

            final String Tmp
                    = mergeMessages("Higher=" + Higher
                    + " not greater than Lower=" + Lower,
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code Higher} is lesser than {@code Lower}.
     *
     * @param inLOG a {@code Logger}
     * @param Higher The higher {@code float} to check
     * @param Lower The lower {@code float} to check
     * @param messages messages to add to the log 
     */
    public static void greaterOrEqualToFloat(
            Logger inLOG, float Higher, float Lower,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking values
        if ( Higher < Lower ) {

            final String Tmp
                    = mergeMessages("Higher=" + Higher
                    + " not greater than Lower=" + Lower,
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code Higher} is lesser than {@code Lower}.
     *
     * @param inLOG a {@code Logger}
     * @param Higher The higher {@code int} to check
     * @param Lower The lower {@code int} to check
     * @param messages messages to add to the log 
     */
    public static void greaterOrEqualToInteger(
            Logger inLOG, int Higher, int Lower,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking values
        if ( Higher < Lower ) {

            final String Tmp
                    = mergeMessages("Higher=" + Higher
                    + " not greater than Lower=" + Lower,
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code Higher} is lesser than {@code Lower}.
     *
     * @param inLOG a {@code Logger}
     * @param Higher The higher {@code long} to check
     * @param Lower The lower {@code long} to check
     * @param messages messages to add to the log 
     */
    public static void greaterOrEqualToLong(
            Logger inLOG, long Higher, long Lower,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking values
        if ( Higher < Lower ) {

            final String Tmp
                    = mergeMessages("Higher=" + Higher
                    + " not greater than Lower=" + Lower,
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code Higher} is lesser than {@code Lower}.
     *
     * @param inLOG a {@code Logger}
     * @param Higher The higher {@code BigInteger} to check
     * @param Lower The lower {@code BigInteger} to check
     * @param messages messages to add to the log 
     */
    public static void greaterOrEqualToBigInteger(
            Logger inLOG, BigInteger Higher, BigInteger Lower,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameter
        Soundness.nullParameter(LOG, Higher);
        Soundness.nullParameter(LOG, Lower);

        // Checking values
        if ( Higher.compareTo(Lower) < 0 ) {

            final String Tmp
                    = mergeMessages("Higher=" + Higher.toString()
                    + " not greater than Lower=" + Lower.toString(),
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code TheInput} is not an hexadecimal value.
     *
     * @param inLOG a {@code Logger}
     * @param TheInput The {@code String} to check
     * @param messages messages to add to the log 
     */
    public static void hexadecimalValue(Logger inLOG, String TheInput,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameter
        Soundness.nullParameter(LOG, TheInput);

        // Checking values
        if (!TheInput.toLowerCase(Locale.getDefault()).matches("[0-9a-f]*")) {

            final String Tmp
                    = mergeMessages("Not an hexadecimal : " + TheInput,
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code TheInput} contains {@code TheContent}
     *
     * @param inLOG a {@code Logger}
     * @param TheInput The {@code String} input
     * @param TheContent The {@code String} content
     * @param messages messages to add to the log 
     */
    public static void doesNotContain(
            Logger inLOG, String TheInput, String TheContent,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameters
        Soundness.nullParameter(LOG, TheInput);
        Soundness.nullParameter(LOG, TheContent);

        if (-1!=TheInput.indexOf(TheContent)) {

            final String Tmp
                    = mergeMessages(TheInput + " should not contain '"
                    + TheContent + "'",
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if {@code child} is not an instance of the
     * {@code parent} class.
     *
     * @param inLOG a {@code Logger}
     * @param parent The parent {@code Object}
     * @param child The child {@code Object}
     * @param messages messages to add to the log 
     */
    public static void isInstanceOf(Logger inLOG, Object parent, Object child,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameters
        Soundness.nullParameter(LOG, parent);
        Soundness.nullParameter(LOG, child);

        if ( ! parent.getClass().isInstance(child) )  {

            final String Tmp
                    = mergeMessages(child.getClass().getName()
                    + " is not an instance of " + parent.getClass().getName(),
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Throws a {@link IllegalArgumentException } and logs an error entry
     * if the {@code implementing} object does not
     * implement the {@code implemented} class.
     *
     * @param inLOG a {@code Logger}
     * @param implementing The parent {@code Object}
     * @param implemented The child {@code Object}
     * @param messages messages to add to the log 
     */
    @SuppressWarnings("unchecked")
    public static void doesImplement(
            Logger inLOG, Object implementing, Class implemented,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        // Checking parameters
        Soundness.nullParameter(LOG, implementing);
        Soundness.nullParameter(LOG, implemented);

        if ( ! implemented.isAssignableFrom(implementing.getClass()) )  {

            final String Tmp
                    = mergeMessages(implementing.getClass().getName()
                    + " does not implement/extend "
                    + implemented.getClass().getName(),
                    messages);
            final OutOfExpectationsException Ex
                    = new OutOfExpectationsException(Tmp);
            inLOG.error(Tmp, Ex);
            throw Ex;

        }

    }

    /**
     * Automatically throws a runtime exception and logs an error when
     * the method is called.
     *
     * @param inLOG a {@code Logger}
     * @param Ex an exception or <tt>null</tt>
     * @param messages messages to add to the log 
     */
    public static void unreachableCodeReached(Logger inLOG, Exception Ex,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        RuntimeException NewEx = null;
        final String NewText
                = mergeMessages("Unreachable code reached: "
                + LOG.getName(),
                messages);

        if (Ex!=null) {
            NewEx = new UnreachableCodeReachedException(NewText, NewEx);
        } else {
            NewEx = new UnreachableCodeReachedException(NewText);
        }

        LOG.error(NewText, Ex);
        throw NewEx;

    }

    /**
     * Automatically throws a runtime exception and logs an error when the
     * method is called.
     *
     * @param inLOG a {@code Logger}
     * @param msg a logging message
     * @param messages messages to add to the log 
     */
    public static void unreachableCodeReached(Logger inLOG, String msg,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        RuntimeException NewEx = null;
        final String NewText
                    = mergeMessages("Unreachable code reached: " + msg,
                    messages);
        NewEx = new UnreachableCodeReachedException(NewText, NewEx);

        LOG.error(NewText, NewEx);
        throw NewEx;

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a byte.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToByte(Logger inLOG, short inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( ( inValue < Byte.MIN_VALUE ) || ( inValue > Byte.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to byte: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a byte.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToByte(Logger inLOG, int inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);


        if ( ( inValue < Byte.MIN_VALUE ) || ( inValue > Byte.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to byte: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a byte.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToByte(Logger inLOG, long inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);


        if ( ( inValue < Byte.MIN_VALUE ) || ( inValue > Byte.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to byte: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a byte.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToByte(Logger inLOG, float inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);


        if ( ( inValue < Byte.MIN_VALUE ) || ( inValue > Byte.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to byte: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a byte.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToByte(Logger inLOG, double inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( ( inValue < Byte.MIN_VALUE ) || ( inValue > Byte.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to byte: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a short.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToShort(Logger inLOG, int inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( ( inValue < Short.MIN_VALUE ) || ( inValue > Short.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to short: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a short.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToShort(Logger inLOG, long inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( ( inValue < Short.MIN_VALUE ) || ( inValue > Short.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to short: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a short.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToShort(Logger inLOG, float inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);


        if ( ( inValue < Short.MIN_VALUE ) || ( inValue > Short.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to short: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a short.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToShort(Logger inLOG, double inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( ( inValue < Short.MIN_VALUE ) || ( inValue > Short.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to short: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into an integer.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToInt(Logger inLOG, long inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( ( inValue < Integer.MIN_VALUE )
                || ( inValue > Integer.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to integer: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into an integer.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToInt(Logger inLOG, float inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( ( inValue < Integer.MIN_VALUE )
                || ( inValue > Integer.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to integer: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into an integer.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToInt(Logger inLOG, double inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( ( inValue < Integer.MIN_VALUE )
                || ( inValue > Integer.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to integer: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a long.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToLong(Logger inLOG, float inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( ( inValue < Long.MIN_VALUE ) || ( inValue > Long.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to long: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a long.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToLong(Logger inLOG, double inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( ( inValue < Long.MIN_VALUE ) || ( inValue > Long.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to long: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

    /**
     * Throws a runtime and logs an error is provided value cannot be converted
     * into a float.
     *
     * @param inLOG a {@code Logger}
     * @param inValue a value to convert
     * @param messages messages to add to the log 
     */
    public static void isConvertibleToFloat(Logger inLOG, double inValue,
            String... messages) {
        
        if ( !SOUNDNESS_ENABLED ) return;
        Soundness.nullParameter(LOG, inLOG);

        if ( ( inValue < -Float.MAX_VALUE ) || ( inValue > Float.MAX_VALUE ) ) {

            final String NewText
                    = mergeMessages("Not convertible to float: " + inValue,
                    messages);
            final OutOfExpectationsException NewEx
                    = new OutOfExpectationsException(NewText);
            LOG.error(NewText, NewEx);
            throw NewEx;

        }

    }

}